<!DOCTYPE html>
            
<HTML>
<HEAD>
<meta name="booktitle" content="Developing Applications With Objective Caml" >
 <meta charset="ISO-8859-1"><meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
<META name="GENERATOR" content="hevea 1.05-7 of 2000-02-24">
<META NAME="Author" CONTENT="Christian.Queinnec@lip6.fr">
<LINK rel=stylesheet type="text/css" href="videoc-ocda.css">
<script language="JavaScript" src="videoc.js"><!--
//--></script>
<TITLE>
 Functional Style
</TITLE>
</HEAD>
<BODY class="regularBody">
<A HREF="book-ora144.html"><IMG SRC ="previous_motif.gif" ALT="Previous"></A>
<A HREF="index.html"><IMG SRC ="contents_motif.gif" ALT="Contents"></A>
<A HREF="book-ora146.html"><IMG SRC ="next_motif.gif" ALT="Next"></A>
<HR>

<H2> Functional Style</H2>
Object-oriented programming usually has an imperative style. A message is
sent to an object that physically modifies its internal state (i.e. its data
fields). It is also possible to use a functional approach to
object-oriented programming: sending a message returns a new object.<BR>
<BR>

<H4> Object Copy</H4>
<A NAME="@concepts334"></A>
<A NAME="@fonctions397"></A>
<A NAME="@fonctions398"></A>
Objective CAML provides a special syntactic construct for returning a copy of an object
<TT>self</TT> with some of the fields modified.


<H3> Syntax </H3> <HR>


<B>{&lt;</B> 
<I>name</I><SUB><I><FONT SIZE=2>1</FONT></I></SUB><B>=</B><I>expr</I><SUB><I><FONT SIZE=2>1</FONT></I></SUB><B>;</B>...;
<I>name</I><SUB><I><FONT SIZE=2><I>n</I></FONT></I></SUB><B>=</B><I>expr</I><SUB><I><FONT SIZE=2><I>n</I></FONT></I></SUB> 
<B>&gt;}</B>



<HR>


This way we can define functional points where methods for relative moves
have no side effect, but instead return a new point.


<PRE><BR># <B>class</B><CODE> </CODE>f_point<CODE> </CODE>p<CODE> </CODE><CODE>=</CODE><BR><CODE> </CODE><CODE> </CODE><B>object</B><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>inherit</B><CODE> </CODE>point<CODE> </CODE>p<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE>f_rmoveto_x<CODE> </CODE><TT>(</TT>dx<TT>)</TT><CODE> </CODE><CODE>=</CODE><CODE> </CODE><CODE>{&lt;</CODE><CODE> </CODE>x<CODE> </CODE><CODE>=</CODE><CODE> </CODE>x<CODE> </CODE><CODE>+</CODE><CODE> </CODE>dx<CODE> </CODE><CODE>&gt;}</CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE>f_rmoveto_y<CODE> </CODE><TT>(</TT>dy<TT>)</TT><CODE> </CODE><CODE>=</CODE><CODE> </CODE><CODE>{&lt;</CODE><CODE> </CODE>y<CODE> </CODE><CODE>=</CODE><CODE> </CODE>y<CODE> </CODE><CODE>+</CODE><CODE> </CODE>dy<CODE> </CODE><CODE>&gt;}</CODE><BR><CODE> </CODE><CODE> </CODE><B>end</B><CODE> </CODE>;;<BR><CODE>class f_point :</CODE><BR><CODE>  int * int -&gt;</CODE><BR><CODE>  object ('a)</CODE><BR><CODE>    val mutable x : int</CODE><BR><CODE>    val mutable y : int</CODE><BR><CODE>    method distance : unit -&gt; float</CODE><BR><CODE>    method f_rmoveto_x : int -&gt; 'a</CODE><BR><CODE>    method f_rmoveto_y : int -&gt; 'a</CODE><BR><CODE>    method get_x : int</CODE><BR><CODE>    method get_y : int</CODE><BR><CODE>    method moveto : int * int -&gt; unit</CODE><BR><CODE>    method print : unit -&gt; unit</CODE><BR><CODE>    method rmoveto : int * int -&gt; unit</CODE><BR><CODE>    method to_string : unit -&gt; string</CODE><BR><CODE>  end</CODE><BR>

</PRE>
<BR>
<BR>
With the new methods, movement no longer modifies the receiving object; instead a new object
is returned that reflects the movement.


<PRE><BR># <B>let</B><CODE> </CODE>p<CODE> </CODE><CODE>=</CODE><CODE> </CODE><B>new</B><CODE> </CODE>f_point<CODE> </CODE><TT>(</TT><CODE>1</CODE><CODE>,</CODE><CODE>1</CODE><TT>)</TT><CODE> </CODE>;;<BR><CODE>val p : f_point = &lt;obj&gt;</CODE><BR># print_string<CODE> </CODE><TT>(</TT>p#to_string()<TT>)</TT><CODE> </CODE>;;<BR><CODE>( 1, 1)- : unit = ()</CODE><BR># <B>let</B><CODE> </CODE>q<CODE> </CODE><CODE>=</CODE><CODE> </CODE>p#f_rmoveto_x<CODE> </CODE><CODE>2</CODE><CODE> </CODE>;;<BR><CODE>val q : f_point = &lt;obj&gt;</CODE><BR># print_string<CODE> </CODE><TT>(</TT>p#to_string()<TT>)</TT><CODE> </CODE>;;<BR><CODE>( 1, 1)- : unit = ()</CODE><BR># print_string<CODE> </CODE><TT>(</TT>q#to_string()<TT>)</TT><CODE> </CODE>;;<BR><CODE>( 3, 1)- : unit = ()</CODE><BR>

</PRE>
<BR>
<BR>
Since these methods construct an object, it is possible to send a message
directly to the result of the method <TT>f_rmoveto_x</TT>.


<PRE><BR># print_string<CODE> </CODE><TT>(</TT><TT>(</TT>p#f_rmoveto_x<CODE> </CODE><CODE>3</CODE><TT>)</TT>#to_string()<TT>)</TT><CODE> </CODE>;;<BR><CODE>( 4, 1)- : unit = ()</CODE><BR>

</PRE>
<BR>
<BR>
The result type of the methods <TT>f_rmoveto_x</TT> and <TT>f_rmoveto_y</TT>
is the type of the instance of the defined class, as shown by the <I>'a</I>
in the type of <TT>f_rmoveto_x</TT>. 


<PRE><BR># <B>class</B><CODE> </CODE>f_colored_point<CODE> </CODE><TT>(</TT>xc<CODE>,</CODE><CODE> </CODE>yc<TT>)</TT><CODE> </CODE><TT>(</TT>c<CODE>:</CODE>string<TT>)</TT><CODE> </CODE><CODE>=</CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>object</B><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>inherit</B><CODE> </CODE>f_point<TT>(</TT>xc<CODE>,</CODE><CODE> </CODE>yc<TT>)</TT><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>val</B><CODE> </CODE>color<CODE> </CODE><CODE>=</CODE><CODE> </CODE>c<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE>get_c<CODE> </CODE><CODE>=</CODE><CODE> </CODE>color<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>end</B><CODE> </CODE>;;<BR><CODE>class f_colored_point :</CODE><BR><CODE>  int * int -&gt;</CODE><BR><CODE>  string -&gt;</CODE><BR><CODE>  object ('a)</CODE><BR><CODE>    val color : string</CODE><BR><CODE>    val mutable x : int</CODE><BR><CODE>    val mutable y : int</CODE><BR><CODE>    method distance : unit -&gt; float</CODE><BR><CODE>    method f_rmoveto_x : int -&gt; 'a</CODE><BR><CODE>    method f_rmoveto_y : int -&gt; 'a</CODE><BR><CODE>    method get_c : string</CODE><BR><CODE>    method get_x : int</CODE><BR><CODE>    method get_y : int</CODE><BR><CODE>    method moveto : int * int -&gt; unit</CODE><BR><CODE>    method print : unit -&gt; unit</CODE><BR><CODE>    method rmoveto : int * int -&gt; unit</CODE><BR><CODE>    method to_string : unit -&gt; string</CODE><BR><CODE>  end</CODE><BR>

</PRE>
<BR>
<BR>
Sending <TT>f_rmoveto_x</TT> to an instance of <TT>f_colored_point</TT>
returns a new instance of <TT>f_colored_point</TT>.


<PRE><BR># <B>let</B><CODE> </CODE>fpc<CODE> </CODE><CODE>=</CODE><CODE> </CODE><B>new</B><CODE> </CODE>f_colored_point<CODE> </CODE><TT>(</TT><CODE>2</CODE><CODE>,</CODE><CODE>3</CODE><TT>)</TT><CODE> </CODE><CODE>"blue"</CODE><CODE> </CODE>;;<BR><CODE>val fpc : f_colored_point = &lt;obj&gt;</CODE><BR># <B>let</B><CODE> </CODE>fpc2<CODE> </CODE><CODE>=</CODE><CODE> </CODE>fpc#f_rmoveto_x<CODE> </CODE><CODE>4</CODE><CODE> </CODE>;;<BR><CODE>val fpc2 : f_colored_point = &lt;obj&gt;</CODE><BR># fpc2#get_c;;<BR><CODE>- : string = "blue"</CODE><BR>

</PRE>
<BR>
<BR>
One can also obtain a copy of an arbitrary object, using the the primitive
<TT>copy</TT> from module <TT>Oo</TT>:
<A NAME="@fonctions399"></A>


<PRE><BR># Oo.copy<CODE> </CODE>;;<BR><CODE>- : (&lt; .. &gt; as 'a) -&gt; 'a = &lt;fun&gt;</CODE><BR># <B>let</B><CODE> </CODE>q<CODE> </CODE><CODE>=</CODE><CODE> </CODE>Oo.copy<CODE> </CODE>p<CODE> </CODE>;;<BR><CODE>val q : f_point = &lt;obj&gt;</CODE><BR># print_string<CODE> </CODE><TT>(</TT>p#to_string()<TT>)</TT><CODE> </CODE>;;<BR><CODE>( 1, 1)- : unit = ()</CODE><BR># print_string<CODE> </CODE><TT>(</TT>q#to_string()<TT>)</TT><CODE> </CODE>;;<BR><CODE>( 1, 1)- : unit = ()</CODE><BR># p#moveto<TT>(</TT><CODE>4</CODE><CODE>,</CODE><CODE>5</CODE><TT>)</TT><CODE> </CODE>;;<BR><CODE>- : unit = ()</CODE><BR># print_string<CODE> </CODE><TT>(</TT>p#to_string()<TT>)</TT><CODE> </CODE>;;<BR><CODE>( 4, 5)- : unit = ()</CODE><BR># print_string<CODE> </CODE><TT>(</TT>q#to_string()<TT>)</TT><CODE> </CODE>;;<BR><CODE>( 1, 1)- : unit = ()</CODE><BR>

</PRE>
<BR>
<BR>

<H4> Example: a Class for Lists</H4>
A functional method may use the object itself, <TT>self</TT>, to compute the
value to be returned. Let us illustrate this point by defining a simple
hierarchy of classes for representing lists of integers.<BR>
<BR>
First we define the abstract class, parameterized by the type of list
elements.


<PRE><BR># <B>class</B><CODE> </CODE><B>virtual</B><CODE> </CODE><CODE>[</CODE><I>'a</I><CODE>]</CODE><CODE> </CODE>o_list<CODE> </CODE>()<CODE> </CODE><CODE>=</CODE><BR><CODE> </CODE><B>object</B><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE><B>virtual</B><CODE> </CODE>empty<CODE> </CODE><CODE>:</CODE><CODE> </CODE>unit<CODE> </CODE>-&gt;<CODE> </CODE>bool<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE><B>virtual</B><CODE> </CODE>cons<CODE> </CODE><CODE> </CODE><CODE>:</CODE><CODE> </CODE><I>'a</I><CODE> </CODE>-&gt;<CODE> </CODE><I>'a</I><CODE> </CODE>o_list<CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE><B>virtual</B><CODE> </CODE>head<CODE> </CODE><CODE>:</CODE><CODE> </CODE><CODE> </CODE><I>'a</I><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE><B>virtual</B><CODE> </CODE>tail<CODE> </CODE><CODE>:</CODE><CODE> </CODE><I>'a</I><CODE> </CODE>o_list<BR><CODE> </CODE><B>end</B>;;<BR>

</PRE>
<BR>
<BR>
We define the class of non empty lists.


<PRE><BR># <B>class</B><CODE> </CODE><CODE> </CODE><CODE>[</CODE><I>'a</I><CODE>]</CODE><CODE> </CODE>o_cons<CODE> </CODE><TT>(</TT>n<CODE> </CODE><CODE>,</CODE>l<TT>)</TT><CODE> </CODE><CODE> </CODE><CODE>=</CODE><BR><CODE> </CODE><B>object</B><CODE> </CODE><TT>(</TT>self<TT>)</TT><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>inherit</B><CODE> </CODE><CODE>[</CODE><I>'a</I><CODE>]</CODE><CODE> </CODE>o_list<CODE> </CODE>()<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>val</B><CODE> </CODE>car<CODE> </CODE><CODE>=</CODE><CODE> </CODE>n<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>val</B><CODE> </CODE>cdr<CODE> </CODE><CODE>=</CODE><CODE> </CODE>l<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE>empty<CODE> </CODE>()<CODE> </CODE><CODE>=</CODE><CODE> </CODE><B>false</B><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE>cons<CODE> </CODE>x<CODE> </CODE><CODE>=</CODE><CODE> </CODE><B>new</B><CODE> </CODE>o_cons<CODE> </CODE><TT>(</TT>x<CODE>,</CODE><CODE> </CODE><TT>(</TT>self<CODE> </CODE><CODE>:</CODE><CODE> </CODE><I>'a</I><CODE> </CODE>#o_list<CODE> </CODE><CODE>:&gt;</CODE><CODE> </CODE><I>'a</I><CODE> </CODE>o_list<TT>)</TT><TT>)</TT><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE>head<CODE> </CODE><CODE>=</CODE><CODE> </CODE>car<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE>tail<CODE> </CODE><CODE>=</CODE><CODE> </CODE>cdr<BR><CODE> </CODE><B>end</B>;;<BR><CODE>class ['a] o_cons :</CODE><BR><CODE>  'a * 'a o_list -&gt;</CODE><BR><CODE>  object</CODE><BR><CODE>    val car : 'a</CODE><BR><CODE>    val cdr : 'a o_list</CODE><BR><CODE>    method cons : 'a -&gt; 'a o_list</CODE><BR><CODE>    method empty : unit -&gt; bool</CODE><BR><CODE>    method head : 'a</CODE><BR><CODE>    method tail : 'a o_list</CODE><BR><CODE>  end</CODE><BR>

</PRE>
<BR>
<BR>
We should note that method <TT>cons</TT> returns a new instance of
<I>'a o_cons</I>. To this effect, the type of <TT>self</TT> is constrained
to <I>'a #o_list</I>, then subtyped to <I>'a o_list</I>. Without
subtyping, we would obtain an open type (<I>'a #o_list</I>), which appears in the
type of the methods, and is strictly forbidden (see page
<A HREF="book-ora143.html#sec-type-self">??</A>). Without the additional constraint, the type of
<TT>self</TT> could not be a subtype of <I>'a o_list</I>.<BR>
<BR>
This way we obtain the expected type for method <TT>cons</TT>. So now we know
the trick and we define the class of empty lists.


<PRE><BR># <B>exception</B><CODE> </CODE>EmptyList<CODE> </CODE>;;<BR># <B>class</B><CODE> </CODE><CODE>[</CODE><I>'a</I><CODE>]</CODE><CODE> </CODE>o_nil<CODE> </CODE>()<CODE> </CODE><CODE>=</CODE><BR><CODE> </CODE><CODE> </CODE><B>object</B><TT>(</TT>self<TT>)</TT><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>inherit</B><CODE> </CODE><CODE>[</CODE><I>'a</I><CODE>]</CODE><CODE> </CODE>o_list<CODE> </CODE>()<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE>empty<CODE> </CODE>()<CODE> </CODE><CODE>=</CODE><CODE> </CODE><B>true</B><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE>cons<CODE> </CODE>x<CODE> </CODE><CODE>=</CODE><CODE> </CODE><B>new</B><CODE> </CODE>o_cons<CODE> </CODE><TT>(</TT>x<CODE>,</CODE><CODE> </CODE><TT>(</TT>self<CODE> </CODE><CODE>:</CODE><CODE> </CODE><I>'a</I><CODE> </CODE>#o_list<CODE> </CODE><CODE>:&gt;</CODE><CODE> </CODE><I>'a</I><CODE> </CODE>o_list<TT>)</TT><TT>)</TT><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE>head<CODE> </CODE><CODE>=</CODE><CODE> </CODE>raise<CODE> </CODE>EmptyList<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE>tail<CODE> </CODE><CODE>=</CODE><CODE> </CODE>raise<CODE> </CODE>EmptyList<BR><CODE> </CODE><CODE> </CODE><B>end</B><CODE> </CODE>;;<BR>

</PRE>
<BR>
<BR>
First of all we build an instance of the empty list, and then a list of integers.


<PRE><BR># <B>let</B><CODE> </CODE>i<CODE> </CODE><CODE>=</CODE><CODE> </CODE><B>new</B><CODE> </CODE>o_nil<CODE> </CODE>();;<BR><CODE>val i : '_a o_nil = &lt;obj&gt;</CODE><BR># <B>let</B><CODE> </CODE>l<CODE> </CODE><CODE>=</CODE><CODE> </CODE><B>new</B><CODE> </CODE>o_cons<CODE> </CODE><TT>(</TT><CODE>3</CODE><CODE>,</CODE>i<TT>)</TT>;;<BR><CODE>val l : int o_list = &lt;obj&gt;</CODE><BR># l#head;;<BR><CODE>- : int = 3</CODE><BR># l#tail#empty();;<BR><CODE>- : bool = true</CODE><BR>

</PRE>

The last expression sends the message <EM>tail</EM> to the list containing the
integer 3, which triggers the method <TT>tail</TT> from the class <I>'a o_cons</I>.
The message <EM>empty()</EM>, which returns <TT>true</TT>, is sent to this result.
You can see that the method which has been executed is <TT>empty</TT> from
the class <I>'a o_nil</I>.<BR>
<BR>
<HR>
<A HREF="book-ora144.html"><IMG SRC ="previous_motif.gif" ALT="Previous"></A>
<A HREF="index.html"><IMG SRC ="contents_motif.gif" ALT="Contents"></A>
<A HREF="book-ora146.html"><IMG SRC ="next_motif.gif" ALT="Next"></A>
</BODY>
</HTML>
